﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel.Composition;
using System.Linq;
using System.Net;
using System.Text;
using System.Windows;
using Caliburn.Micro;
using MvcApplication2.Models;
using Newtonsoft.Json.Linq;

namespace AppReviewerClient
{
    public class AvailableExerciseViewModel : ViewAware
    {
        private ObservableCollection<ExerciseViewModel> _exercises;
        public ObservableCollection<ExerciseViewModel> Exercises
        {
            get { return _exercises; }
            set
            {
                _exercises = value;
                NotifyOfPropertyChange(() => Exercises);
            }
        }

        //private readonly IEnumerable<ExerciseViewModel> _exercises;
        private readonly ShellViewModel _parent;

        private string _username;
        private string _password;

        public AvailableExerciseViewModel(ShellViewModel parent)
        {
            _parent = parent;

            _username = _parent.LoginViewModel.Username;
            _password = _parent.LoginViewModel.Password;

            UpdateListCmd();
        }

        /// <summary>
        /// Aggiorna lista esercizi
        /// </summary>
        public void UpdateListCmd()
        {
            Exercises = null;
            DownloadProgress = 0;

            UpdateExerciseList(string.Format("{0}tester/GetTesterExercise/", ShellViewModel.Host));

        }

        /// <summary>
        /// Una volta scaricata la lista degli esercizi concordati , 
        /// aggiorno lo stato ( toencode, toupload , in base ai dati che ho in locale)
        /// Tutti i video vengono salvati dentro una cartella con convenzione
        /// {username}_{exercise_id}
        /// dove all'interno ci sono tutti i file e un file contentente lo stato di avanzamento.
        /// </summary>
        /// <param name="exs"></param>
        /// <returns></returns>
        private static IEnumerable<ExerciseViewModel> UpdateFromLocal(IEnumerable<ExerciseViewModel> exs)
        {
            foreach (var exerciseViewModel in exs)
            {
                var local = FilepathHelper.GetLocalExercise(exerciseViewModel.ExerciseId);

                if (local != null)
                    exerciseViewModel.LocalExerciseStatus = local.LocalExerciseStatus;
            }

            return exs;
        }
        private bool _isWaiting;
        public bool IsWaiting
        {
            get { return _isWaiting; }
            set
            {
                _isWaiting = value;
                NotifyOfPropertyChange(() => IsWaiting);
            }
        }

        void UpdateExerciseList(string url)
        {
            try
            {
                IsWaiting = true;
                var webClient = new WebClientEx { Credentials = new NetworkCredential(_username, _password) };

                webClient.UploadProgressChanged += WebClientUploadProgressChanged;
                webClient.UploadValuesCompleted += WebClientGetExerciseCompleted;
                webClient.UploadValuesAsync(new Uri(url), new NameValueCollection() { { "username", _username }, { "password", _password } });


            }
            catch (Exception exception)
            {
                ActionText = "Error !";
            }
        }

        void WebClientGetExerciseCompleted(object sender, UploadValuesCompletedEventArgs e)
        {
            IsWaiting = false;
            try
            {
                ActionText = "Updating";

                var json = Encoding.UTF8.GetString(e.Result);

                var o = JObject.Parse(json);

                var sizes = (JArray)o["o"];

                var exerciseList = new List<ExerciseViewModel>();
                foreach (var i in sizes)
                {
                    var vm = new ExerciseViewModel
                    {
                        Reward = i["Reward"].ToString(),
                        Title = i["Title"].ToString(),
                        Author = i["Author"].ToString(),
                        ExerciseIdString = i["ExerciseId"].ToString(),
                    };


                    exerciseList.Add(vm);
                }
                var localEX = UpdateFromLocal(exerciseList);

                Exercises = new ObservableCollection<ExerciseViewModel>(localEX);

                ActionText = "Update Completed";
            }
            catch (Exception exception)
            {
                ActionText = "Error !";
            }

        }

        void WebClientUploadProgressChanged(object sender, UploadProgressChangedEventArgs e)
        {
            DownloadProgress = e.ProgressPercentage;
        }


        private string _actionText;
        public string ActionText
        {
            get { return _actionText; }
            set
            {
                _actionText = value;
                NotifyOfPropertyChange(() => ActionText);
            }
        }

        private double _downloadProgress;
        public double DownloadProgress
        {
            get { return _downloadProgress; }
            set
            {
                _downloadProgress = value;
                NotifyOfPropertyChange(() => DownloadProgress);
            }
        }
        public string AvailableExerciseViewTitle
        {
            get { return "Available Exercises"; }
        }

        public void OpenElement(object o)
        {
            _parent.SetActiveExercise((ExerciseViewModel)o);

            ExecuteCancelCommand();

        }

        public void ExecuteCancelCommand()
        {
            (GetView() as Window).Close();
        }
    }

    /// <summary>
    /// Classe che memorizza informazioni su esercizio da svolgere in locale.
    /// Viene salvata su file.
    /// Quando apro esercizio creo una cartella temporanea con nome temp_username_threadmessageid
    /// </summary>
    [Serializable]
    public class LocalExercise
    {
        public int ThreadMessageId { get; set; }

        public LocalExerciseStatus LocalExerciseStatus { get; set; }
    }

    public enum LocalExerciseStatus
    {
        ToBegin,
        Beginned,
        ToEncode,
        ToUpload,
        Ended,
    }

    // unire con upload item ??
    public class ExerciseViewModel
    {
        public int ExerciseId { get { return int.Parse(ExerciseIdString); } }
        public string ExerciseIdString { get; set; }
        public string Reward { get; set; }
        public string Title { get; set; }
        public string Author { get; set; }
        public LocalExerciseStatus LocalExerciseStatus { get; set; }
    }
}

